#pragma once

#include <Singleton.h>
#include <FunctionMap.h>

struct MSG_BASE;
class User;
class GameDBProxySession;
class AccountDBProxySession;
class GameServerSession;
class BattleServerSession;
class FieldServerSession;
class AgentServerSession;
class MasterServerSession;
class GuildServerSession;

class PacketHandler : public util::Singleton<PacketHandler>
{
	typedef VOID (*fnHandler_CW)( User *pUser, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_DW)( GameDBProxySession *pGameDBProxySession, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_TW)( AccountDBProxySession *pAccountDBProxySession, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_GW)( GameServerSession *pGameServerSession, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_BW)( BattleServerSession *pBattleServerSession, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_FW)( FieldServerSession *pFieldServerSession, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_AW)( AgentServerSession *pAgentServerSession, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_MW)( MasterServerSession *pMasterServerSession, MSG_BASE *pMsg, WORD wSize );
	typedef VOID (*fnHandler_WZ)( GuildServerSession *pGuildServerSession, MSG_BASE *pMsg, WORD wSize );

public:
	PacketHandler();
	~PacketHandler();

	BOOL			RegisterPackets();

	BOOL			ParsePacket_CW( User *pUser, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_DW( GameDBProxySession *pGameDBProxySession, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_TW( AccountDBProxySession *pAccountDBProxySession, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_GW( GameServerSession *pGameServerSession, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_BW( BattleServerSession *pBattleServerSession, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_FW( FieldServerSession *pFieldServerSession, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_AW( AgentServerSession *pAgentServerSession, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_MW( MasterServerSession *pMasterServerSession, MSG_BASE *pMsg, WORD wSize );
	BOOL			ParsePacket_WZ( GuildServerSession *pGuildServerSession, MSG_BASE *pMsg, WORD wSize );

private:
	BOOL			RegClientPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_CW fnHandler );
	BOOL			RegGameDBProxyPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_DW fnHandler );
	BOOL			RegAccountDBProxyPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_TW fnHandler );
	BOOL			RegGameServerPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_GW fnHandler );
	BOOL			RegBattleServerPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_BW fnHandler );
	BOOL			RegFieldServerPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_FW fnHandler );
	BOOL			RegAgentServerPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_AW fnHandler );
	BOOL			RegMasterServerPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_MW fnHandler );
	BOOL			RegGuildServerPacket( BYTE category, BYTE protocol, PacketHandler::fnHandler_WZ fnHandler );

	struct FUNC_CW : public util::BASE_FUNC
	{
		fnHandler_CW	m_fnHandler;
	};
	struct FUNC_DW : public util::BASE_FUNC
	{
		fnHandler_DW	m_fnHandler;
	};
	struct FUNC_TW : public util::BASE_FUNC
	{
		fnHandler_TW	m_fnHandler;
	};
	struct FUNC_GW : public util::BASE_FUNC
	{
		fnHandler_GW	m_fnHandler;
	};
	struct FUNC_BW : public util::BASE_FUNC
	{
		fnHandler_BW	m_fnHandler;
	};
	struct FUNC_FW : public util::BASE_FUNC
	{
		fnHandler_FW	m_fnHandler;
	};
	struct FUNC_AW : public util::BASE_FUNC
	{
		fnHandler_AW	m_fnHandler;
	};
	struct FUNC_MW : public util::BASE_FUNC
	{
		fnHandler_MW	m_fnHandler;
	};
	struct FUNC_WZ : public util::BASE_FUNC
	{
		fnHandler_WZ	m_fnHandler;
	};

	util::FunctionMap		*m_pFuncMap_CW;
	util::FunctionMap		*m_pFuncMap_DW;
	util::FunctionMap		*m_pFuncMap_TW;
	util::FunctionMap		*m_pFuncMap_GW;
	util::FunctionMap		*m_pFuncMap_BW;
	util::FunctionMap		*m_pFuncMap_FW;
	util::FunctionMap		*m_pFuncMap_AW;
	util::FunctionMap		*m_pFuncMap_MW;
	util::FunctionMap		*m_pFuncMap_WZ;
};
